package ChatNI;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.List;

import Controller.User;
import Signals.Goodbye;
import Signals.Hello;
import Signals.HelloAck;
import Signals.TextMessage;
import Signals.typeContenu;

public class UDPSender {

	private DatagramSocket socket;
	private ChatNI ni;
	private ByteArrayOutputStream baos;
	private ObjectOutputStream oos;

	/**
	 * Initialize the attributes 
	 * @param ni Network du ChatSystem
	 */
	public UDPSender(ChatNI ni) {
		this.ni = ni;
		// Construct the socket
		try {
			socket = new DatagramSocket() ;
			baos = new ByteArrayOutputStream();
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(e.getClass().toString() + "Socket not created");
		}
	}

	/**
	 * send Hello Message to everyone
	 */
	public void sendHello(){
		try {
			// we create our Hello signals
			Hello hello = new Hello();
			hello.setNickname(ni.getLocalUser().getNameIP());
			System.out.println("UDPSender : Hello signal created");
			baos.reset();
			oos = new ObjectOutputStream(baos);
			// we put our Hello in the ObjectOutputStream
			oos.writeObject(hello);
			this.sendSignal(baos,InetAdressSearcher.getLocalBroadcastIp());

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("UDPSender : sendHello : Coulnd not send the Hello");
		}

	}
	/**
	 * send Hello Ack to destination user
	 * @param user the recipient 
	 */
	public void sendHelloAck(User user){
		try {
			// we create our HelloAck signals
			HelloAck helloAck = new HelloAck();
			helloAck.setTypeContenu(typeContenu.HELLOACK);
			//we set put the localuser name in the message
			helloAck.setNickname(ni.getLocalUser().getNameIP());
			System.out.println("UDPSender : HelloAck signal created");
			baos.reset();
			oos = new ObjectOutputStream(baos);
			// we put our Hello in the ObjectOutputStream
			oos.writeObject(helloAck);
			// send the signal to the chosen user 
			InetAddress ip = Inet4Address.getByName(user.getIp());
			this.sendSignal(baos,ip);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("UDPSender : sendHello : Coulnd not send the HelloAck");
		}
	}


	/**
	 * Send the textmsg to the list of destination users
	 *  @param msg The message the user want to send
	 *  @param dest The list of User to which we want to send the TextMessage
	 */
	public void sendTextMessage(String msg, List<User> dest ){
		try {
			// we create our HelloAck signals
			TextMessage txtmsg = new TextMessage(msg,User.FromUserListToStringList(dest));
			txtmsg.setTypeContenu(typeContenu.TEXTMESSAGE);
			//we set put the localuser name in the message
			txtmsg.setNickname(ni.getLocalUser().getNameIP());			
			System.out.println("UDPSender : Message signal created");
			baos.reset();
			oos = new ObjectOutputStream(baos);
			// we put our Hello in the ObjectOutputStream
			oos.writeObject(txtmsg);
			// send the signal to all the chosen users
			for (User u: dest){
				InetAddress ip = Inet4Address.getByName(u.getIp());
				this.sendSignal(baos,ip);
			}			

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("UDPSender : sendTextMessage : Coulnd not send the TEXTMESSAGE");
		}
	}

	/**
	 * send Goodbye to everyone
	 */
	public void sendGoodbye(){
		try {
			// we create our Goodbye signals
			Goodbye goodbye = new Goodbye();
			goodbye.setNickname(ni.getLocalUser().getNameIP());
			System.out.println("UDPSender : Goodbye signal created");
			baos.reset();
			oos = new ObjectOutputStream(baos);
			// we put our Hello in the ObjectOutputStream
			oos.writeObject(goodbye);
			this.sendSignal(baos,InetAdressSearcher.getLocalBroadcastIp());

		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("UDPSender : sendGoodbye : Error");
		}
		this.socket.close();


	}

	/**
	 * method that send a given ObjectOutputStream to the given Address
	 * @param baos ByteArrayOutputStream we want to send
	 * @param ip InetAddress to which we want to send the message
	 */
	private void sendSignal(ByteArrayOutputStream baos ,InetAddress ip){
		try {
			byte[] data = baos.toByteArray();
			System.out.println(" UDPSender : sendSignalOnIP = "  + ip.toString());
			DatagramPacket p = new DatagramPacket(data, data.length,ip, ChatNI.portudp);
			socket.send(p);
			System.out.println("UDPSender: sendSignalOnIP : Signal send");

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(e.getClass().toString() + " : Could not send the Signal properly");
		}
	}


}

